/*
 * Copyright (c) 2020 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.lcw.library.imagepicker.layouthelper;

import com.lcw.library.imagepicker.ResourceTable;
import com.lcw.library.imagepicker.data.ItemType;
import com.lcw.library.imagepicker.data.MediaFile;
import com.lcw.library.imagepicker.manager.ConfigManager;
import com.lcw.library.imagepicker.manager.SelectionManager;
import com.lcw.library.imagepicker.utils.ResUtil;
import com.lcw.library.imagepicker.utils.TextUtils;
import com.lcw.library.imagepicker.utils.Utils;
import com.lcw.library.imagepicker.view.SquareRelativeLayout;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.Text;
import ohos.agp.components.Image;
import ohos.app.Context;
import ohos.media.image.PixelMap;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static ohos.agp.utils.LayoutAlignment.TOP;

public class VirtualLayoutManager {
    private static final String TAG = VirtualLayoutManager.class.getSimpleName();
    private List<BaseLayoutHelper> mAdapters = new ArrayList<>();
    private Context mContext;
    private boolean isShowCamera;
    private List<MediaFile> mMediaFileList;
    private String mLastImagePath;

    public VirtualLayoutManager(final Context context, List<MediaFile> mediaFileList) {
        mContext = context;
        mMediaFileList = mediaFileList;
        this.isShowCamera = ConfigManager.getInstance().isShowCamera();
    }

    void setVirtualLayoutManager(final List<BaseLayoutHelper> adapters) {
        mAdapters = adapters;
    }

    Component getComponent(int position, Component component, ComponentContainer parent) {
        BaseLayoutHelper baseLayoutHelper = getLayout(position);
        int newPosition = getNewPosition(position);
        return handleGridLayoutComponent(newPosition, component, parent, (GridLayoutHelper) baseLayoutHelper);
    }

    private int getNewPosition(int position) {
        int count = 0;

        if (mAdapters != null) {
            for (BaseLayoutHelper baseitem : mAdapters) {

                //If position falls within that adapter limit
                if (position < (count + baseitem.getItemCount())) {
                    return (position - count);
                }
                count += baseitem.getItemCount();
            }
        }
        return 0;
    }

    public MediaFile getMediaFile(int position) {
        return mMediaFileList.get(position);
    }

    int getItemComponentType(int position) {
        if (isShowCamera) {
            if (position == 0) {
                return ItemType.ITEM_TYPE_CAMERA;
            }
            //If a camera exists, the position must be -1.
            position--;
        }
        if (mMediaFileList.get(position).getDuration() > 0) {
            return ItemType.ITEM_TYPE_VIDEO;
        } else {
            return ItemType.ITEM_TYPE_IMAGE;
        }
    }

    private Component handleGridLayoutComponent(int newPosition, Component convertComponent, ComponentContainer parent, GridLayoutHelper gridLayoutHelper) {
        convertComponent = new DirectionalLayout(mContext);
        ((DirectionalLayout) convertComponent).setOrientation(Component.HORIZONTAL);
        ComponentContainer.LayoutConfig layoutConfig = convertComponent.getLayoutConfig();
        layoutConfig.width = DirectionalLayout.LayoutConfig.MATCH_PARENT;
        layoutConfig.height = DirectionalLayout.LayoutConfig.MATCH_CONTENT;
        convertComponent.setLayoutConfig(layoutConfig);
        for (int i = 0; i < gridLayoutHelper.getSpanCount(); i++) {
            if (newPosition * gridLayoutHelper.getSpanCount() + i < gridLayoutHelper.getTotalItemCount()) {
                DirectionalLayout dlItemParent = new DirectionalLayout(mContext);
                int height = gridLayoutHelper.getHeight();
                if (gridLayoutHelper.getTotalItemCount() == 1) {
                    dlItemParent.setLayoutConfig(new DirectionalLayout.LayoutConfig(DirectionalLayout.LayoutConfig.MATCH_CONTENT, DirectionalLayout.LayoutConfig.MATCH_CONTENT, TOP, 0));
                } else {
                    dlItemParent.setLayoutConfig(new DirectionalLayout.LayoutConfig(0, DirectionalLayout.LayoutConfig.MATCH_CONTENT, TOP, 1));
                }

                ImagePickerViewHolder viewHolder;
                MediaHolder mediaHolder;
                Component childConvertComponent;
                MediaFile mediaFile;
                int itemPosition = (newPosition * gridLayoutHelper.getSpanCount() + i);
                if (itemPosition == 0) {
                    childConvertComponent = LayoutScatter.getInstance(mContext).parse(ResourceTable.Layout_item_listcontainer_camera, parent, false);
                    viewHolder = new ImagePickerViewHolder(childConvertComponent);
                } else {
                    if (mMediaFileList.get(itemPosition - 1).getDuration() > 0) {
                        childConvertComponent = LayoutScatter.getInstance(mContext).parse(ResourceTable.Layout_item_listcontainer_video, parent, false);
                        viewHolder = new VideoHolder(childConvertComponent);
                        mediaHolder = (MediaHolder) viewHolder;
                        mediaFile = getMediaFile(itemPosition - 1);
                        if (mediaFile != null) {
                            loadMediaImages(mediaHolder, mediaFile);
                            bindMedia(mediaHolder, mediaFile);
                        }
                    } else {
                        childConvertComponent = LayoutScatter.getInstance(mContext).parse(ResourceTable.Layout_item_listcontainer_image, parent, false);
                        viewHolder = new ImageHolder(childConvertComponent);
                        mediaHolder = (MediaHolder) viewHolder;
                        mediaFile = getMediaFile(itemPosition - 1);
                        if (mediaFile != null) {
                            loadMediaImages(mediaHolder, mediaFile);
                            bindMedia(mediaHolder, mediaFile);
                        }
                    }
                }
                if (null != childConvertComponent) {
                    handleOnclickListener(viewHolder, itemPosition);
                    childConvertComponent.setHeight(height);
                    dlItemParent.addComponent(childConvertComponent);
                    ((ComponentContainer) convertComponent).addComponent(dlItemParent);
                }
            } else {
                DirectionalLayout childConvertComponent = new DirectionalLayout(mContext);
                childConvertComponent.setLayoutConfig(new DirectionalLayout.LayoutConfig(0, DirectionalLayout.LayoutConfig.MATCH_CONTENT, TOP, 1));
                ((ComponentContainer) convertComponent).addComponent(childConvertComponent);
            }
        }
        return convertComponent;
    }

    public void bindMedia(MediaHolder mediaHolder, MediaFile mediaFile) {
        String imagePath = mediaFile.getPath();
        Optional<PixelMap> imagePixelMap;
        if (!TextUtils.isEmpty(imagePath)) {
            if (SelectionManager.getInstance().isImageSelect(imagePath)) {
                if (null != mLastImagePath && mLastImagePath.equals(imagePath)) {
                    imagePixelMap = ResUtil.getPixelMap(mContext, ResourceTable.Media_icon_image_check);
                    imagePixelMap.ifPresent(mediaHolder.mImageCheck::setPixelMap);
                    mLastImagePath = "";
                } else {
                    imagePixelMap = ResUtil.getPixelMap(mContext, ResourceTable.Media_icon_image_checked);
                    imagePixelMap.ifPresent(mediaHolder.mImageCheck::setPixelMap);
                    mLastImagePath = imagePath;
                }
            } else {
                imagePixelMap = ResUtil.getPixelMap(mContext, ResourceTable.Media_icon_image_check);
                imagePixelMap.ifPresent(mediaHolder.mImageCheck::setPixelMap);
                mLastImagePath = "";
            }

            if (mediaHolder instanceof ImageHolder) {
                String suffix = imagePath.substring(imagePath.lastIndexOf(".") + 1);
                if (suffix.toUpperCase().equals("GIF")) {
                    ((ImageHolder) mediaHolder).mImageGif.setVisibility(Component.VISIBLE);
                } else {
                    ((ImageHolder) mediaHolder).mImageGif.setVisibility(Component.HIDE);
                }
            }

            if (mediaHolder instanceof VideoHolder) {
                String duration = Utils.getVideoDuration(mediaFile.getDuration());
                ((VideoHolder) mediaHolder).mVideoDuration.setText(duration);
            }
        }
    }

    private void loadMediaImages(MediaHolder mediaHolder, MediaFile mediaFile) {
        mContext.getUITaskDispatcher().asyncDispatch(new Runnable() {
            @Override
            public void run() {
                try {
                    ConfigManager.getInstance().getImageLoader().loadImageUri(mediaHolder.mImageView, mediaFile.getExternalUri());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private void handleOnclickListener(ImagePickerViewHolder viewHolder, int position) {
        if (mOnItemClickListener != null) {
            viewHolder.mSquareRelativeLayout.setClickedListener(new Component.ClickedListener() {
                @Override
                public void onClick(Component view) {
                    mOnItemClickListener.onMediaClick(view, position);
                }
            });

            if (viewHolder instanceof MediaHolder) {
                ((MediaHolder) viewHolder).mImageCheck.setClickedListener(new Component.ClickedListener() {
                    @Override
                    public void onClick(Component view) {
                        mOnItemClickListener.onMediaCheck(viewHolder, view, position);
                    }
                });
            }
        }
    }

    static class ImageHolder extends MediaHolder {
        Image mImageGif;

        ImageHolder(Component itemView) {
            super(itemView);
            mImageGif = (Image) itemView.findComponentById(ResourceTable.Id_iv_item_gif);
        }
    }

    static class VideoHolder extends MediaHolder {
        Text mVideoDuration;

        VideoHolder(Component itemView) {
            super(itemView);
            mVideoDuration = (Text) itemView.findComponentById(ResourceTable.Id_tv_item_videoDuration);
        }
    }

    public static class MediaHolder extends ImagePickerViewHolder {
        Image mImageView;
        Image mImageCheck;

        MediaHolder(Component itemView) {
            super(itemView);
            mImageView = (Image) itemView.findComponentById(ResourceTable.Id_iv_item_image);
            mImageCheck = (Image) itemView.findComponentById(ResourceTable.Id_iv_item_check);
        }
    }

    public static class ImagePickerViewHolder {
        Component itemView;
        SquareRelativeLayout mSquareRelativeLayout;

        ImagePickerViewHolder(Component component) {
            this.itemView = component;
            mSquareRelativeLayout = (SquareRelativeLayout) itemView.findComponentById(ResourceTable.Id_srl_item);
        }
    }

    private BaseLayoutHelper getLayout(int position) {
        int count = 0;

        if (mAdapters != null) {
            for (BaseLayoutHelper baseitem : mAdapters) {

                //If position falls within that adapter limit
                if (position < (count + baseitem.getItemCount())) {
                    return baseitem;
                }
                count += baseitem.getItemCount();
            }
        }
        return null;
    }

    private OnItemClickListener mOnItemClickListener;

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.mOnItemClickListener = onItemClickListener;
    }

    public interface OnItemClickListener {
        void onMediaClick(Component view, int position);

        void onMediaCheck(ImagePickerViewHolder viewHolder, Component view, int position);
    }
}
